package com.hdu.dwh.service.impl;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdu.dwh.mapper.MinioConfMapper;
import com.hdu.dwh.pojos.source_access_pojos.MinioConf;
import com.hdu.dwh.service.MinioService;
import com.hdu.dwh.utils.MinioUtil;
import com.hdu.dwh.vos.MinioTreeNodeVo;

import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;
import io.minio.messages.Item;

@Service
public class MinioServiceImpl extends ServiceImpl<MinioConfMapper, MinioConf> implements MinioService {

    @Override
    public List<MinioTreeNodeVo> getFileTreeById(Long id, String bucketName) throws Exception {
        MinioClient minioClient = this.getMinioClientById(id);
        Iterable<Result<Item>> objectsIterable = minioClient.listObjects(// 调用 MinIO 客户端的 listObjects 方法，返回对象列表
                ListObjectsArgs.builder() // 构建 ListObjectsArgs 对象
                        .bucket(bucketName) // 设置桶名
                        .recursive(true)// 设置是否递归查找
                        .build());// 构建参数并调用 listObjects
        return this.buildTreeStructure(objectsIterable);
    }

    @Override
    public List<String> getAllBuckets(Long id) throws Exception {
        MinioClient minioClient = this.getMinioClientById(id);
        return minioClient.listBuckets().stream().map(bucket -> {
            return bucket.name();
        }).toList();
    }

    private MinioClient getMinioClientById(Long id) {
        MinioConf minioConf = this.getById(id);
        if (minioConf == null) {
            throw new RuntimeException("Minio配置不存在，ID：" + id);
        }
        return new MinioClient.Builder()
        .endpoint(minioConf.getEndpoint())
        .credentials(minioConf.getAccessKey(), minioConf.getSecretKey())
        .build();
    }
    
    /**
     * 构建树状结构
     * @param objectsIterable MinIO对象列表
     * @return 树状结构
     */
    private List<MinioTreeNodeVo> buildTreeStructure(Iterable<Result<Item>> objectsIterable) throws Exception {
        // 根节点列表
        List<MinioTreeNodeVo> rootNodes = new ArrayList<>();
        // 用于存储所有路径节点的映射
        Map<String, MinioTreeNodeVo> nodeMap = new HashMap<>();

        // 遍历所有对象
        for (Result<Item> result : objectsIterable) {
            Item item = result.get();
            String objectName = item.objectName();

            // 按照 '/' 分割路径
            String[] pathParts = objectName.split("/");

            // 逐级构建路径节点
            StringBuilder currentPath = new StringBuilder();
            for (int i = 0; i < pathParts.length; i++) {
                if (i > 0) {
                    currentPath.append("/");
                }
                currentPath.append(pathParts[i]);

                String path = currentPath.toString();
                // 如果节点不存在，则创建节点
                if (!nodeMap.containsKey(path)) {
                    boolean isDir = (i < pathParts.length - 1) || item.isDir(); // 除了最后一个节点，其他都是目录
                    MinioTreeNodeVo node = new MinioTreeNodeVo(pathParts[i], isDir);
                    nodeMap.put(path, node);

                    // 如果是根级节点，添加到根节点列表
                    if (i == 0) {
                        rootNodes.add(node);
                    }
                }
            }
        }

        // 构建父子关系
        for (Map.Entry<String, MinioTreeNodeVo> entry : nodeMap.entrySet()) {
            String path = entry.getKey();
            MinioTreeNodeVo node = entry.getValue();

            // 查找父节点
            int lastSlashIndex = path.lastIndexOf("/");
            if (lastSlashIndex > 0) {
                String parentPath = path.substring(0, lastSlashIndex);
                MinioTreeNodeVo parentNode = nodeMap.get(parentPath);
                if (parentNode != null) {
                    if (parentNode.getChildren() == null) {
                        parentNode.setChildren(new ArrayList<>());
                    }
                    parentNode.getChildren().add(node);
                }
            }
        }

        return rootNodes;
    }
}
